import path from 'path'
import fs from 'fs'
import * as step from '@flow-step/step-toolkit'
import {IParams} from './params'
import fsPromises from 'fs/promises'
import {installGolangciLint} from './install'


export async function setDependentFiles(targetDir: string, golangciLintVersion?: string){
    const currentDir = __dirname
    const copyList = ['builder','diff','report-template.html']
    for (const item of copyList) {
        copyDependency(path.join(currentDir,item), path.join(targetDir,item))
    }
    step.debug(`set permission for diff to 755`)
    fs.chmodSync(path.join(targetDir,'diff'), 0o755)
    step.debug(`set permission for builder to 755`)
    fs.chmodSync(path.join(targetDir,'builder'), 0o755)
    
    // 处理 golangci-lint
    const golangciLintTargetPath = path.join(targetDir,'golangci-lint')
    const version = golangciLintVersion
    
    // 如果版本是1.63，使用原有的dist/golangci-lint
    if (version === "1.63") {
        step.info(`Using default golangci-lint version 1.63`)
        copyDependency(path.join(currentDir,'golangci-lint'), golangciLintTargetPath)
        step.debug(`set permission for golangci-lint to 755`)
        fs.chmodSync(golangciLintTargetPath, 0o755)
    } else {
        // 否则安装新版本并复制到目标目录
        step.info(`Installing golangci-lint version ${version}`)
        const installedPath = await installGolangciLint(version as string)
        // 复制安装的工具到目标目录
        copyDependency(`${installedPath}/golangci-lint-${version}`, golangciLintTargetPath)
        step.debug(`set permission for golangci-lint to 755`)
        fs.chmodSync(golangciLintTargetPath, 0o755)
    }
}


export function copyDependency(source: string, target: string) {
    step.debug(`copy ${source} to ${target}`)
    // 检查目标文件是否存在
    if (fs.existsSync(target)) {
        step.debug(`remove ${target}`)
        fs.unlinkSync(target);
    }
    fs.copyFileSync(source, target)
}

export function checkGoVendor(params: IParams) {
    if (fs.existsSync(path.join(params.projectDir, 'vendor'))) {
        step.info('found vendor')
        step.exportEnvVar('GO111MODULE', 'on')
        step.exportEnvVar('GOFLAGS', '-mod=vendor')
    } else {
        step.exportEnvVar('GO111MODULE', 'auto')
    }
}

export async function readFile(filePath: string): Promise<string> {
    try {
        const data = await fsPromises.readFile(filePath, 'utf-8')
        return data
    } catch (error) {
        step.error(`Error reading file ${filePath}`)
        throw error
    }
}

export async function checkGoVersion(): Promise<void> {
    let commandResult = await step.exec.callOutput('go', ['version'])
    if (commandResult.exitCode!=0 || commandResult.stdoutContent == undefined){
        throw new Error(`go version check failed, please install go first (version >= 1.11)`)
    }

    const versionPattern = /go version go(\d+\.\d+\.\d+)/;
    const match = commandResult.stdoutContent.match(versionPattern);
    if(match && match[1]){
        const version = match[1];
        const versionNumbers = version.split('.').map(Number);
        if (versionNumbers[0] < 1 || (versionNumbers[0] === 1 && versionNumbers[1] < 11)) {
            throw new Error(`golangCodeScan only support go version >= 1.11`)
        }
    }else{
        throw new Error(`Failed to parse Go version`)
    }
}


export function generateLinterArgs(golangciLintVersion: string, fileList: string, exclusion: string) {
    const linterArgs = ['run']
    if (fileList !== '') {
        linterArgs.push(...fileList.trim().split(' ').map(file => file.trim()).filter(file => file !== ''))
    }
    if(golangciLintVersion === '1.63'){
        linterArgs.push('-v', '--exclude-use-default', '--out-format', 'json')
        if (exclusion !== ''){
            linterArgs.push(...exclusion.trim().split(' ').map(file => file.trim()).filter(file => file !== ''))
        }
    } else {
        linterArgs.push('-v', '--output.json.path', 'stdout', '--show-stats=false')
    }

    step.info(`golangci-lint ${linterArgs.join(' ')}`)
    return linterArgs
}
